#include "Entity.h"

#include "AnimationBase.h"

#include "App.h"

namespace Y{

Entity::Entity( ):
	parent_entity(NULL)
{
	App->firstRites(this);
}

Entity::Entity( Entity* parentis ):
	parent_entity(parentis)
{
	App->firstRites(this);
	if ( parentis != NULL ){
		parentis->addChild(this);
	}
}

Entity::~Entity(){
	App->lastRites(this);
	
	if ( parent() != NULL ){ parent()->removeChild(this); }

	for ( int i = 0; i < functorLinks.size(); ++i ){
		functorLinks[i]->removeFunction( this );
	}
}

void Entity::die (){
	App->releaseQ.push_back(this);
}


void Entity::configSubsystem ( std::vector< ConfigComponent >& configVector ){
	handleConfig( configVector );
	if ( configVector.size() > 0 ){
		for ( int i = 0; i < configVector.size(); ++i ){
			std::cout << "\n" << "Extra config component:\t\t" << configVector[i].name.data();
		}
	}
}

void Entity::handleConfig ( std::vector< ConfigComponent >& cv ){
	
	for ( int i = 0; i < cv.size(); ++i ){
		if ( cv[i] == "signal" ){
			addSignal( cv[i].to<const char *>() );
			handled();
		}
	}
}

void Entity::addChild ( Entity* chillun ){
	children.push_back( chillun );
}

void Entity::removeChild ( Entity* chillun ){
	for ( iteratorLoop2(children,it) ){
		if ( (*it) == chillun ){
			children.erase(it);
			break;
		}
	}
}

void Entity::timerSubsystem (float f){
	for ( int i = 0; i < children.size(); ++i ){
		children[i]->timerSubsystem(f);
	}
	timer(f);
}

void Entity::timer (float){	}

void Entity::addAnimation (const OString& nomen, AnimationBase *ptr){
	if ( ptr == NULL ){ return; }
	
	if ( animations.find( nomen ) != animations.end() ){
		delete animations[nomen];
	}
	animations[nomen] = ptr;
	ptr->connect( "finished" , this , FUNC(Entity,removeAnimation,OString,bool) , nomen,false );
}

void Entity::removeAnimation (OString nomen, bool destroy){
	if ( animations.find( nomen ) != animations.end() ){
		if ( destroy ){
			delete animations[nomen];
		}
		animations.erase(nomen);
	}
}

AnimationBase* Entity::animation (const OString& nomen){
	if ( animations.find( nomen ) != animations.end() ){
		return animations[nomen];
	}
	return NULL;
}



void Entity::addSignal ( const char *c ){
	signalMap[c] = new FunctorContainer();
}

void Entity::removeFunctorLink ( FunctorContainer *o ){
	for ( typeof( functorLinks.begin() ) it = functorLinks.begin(); it != functorLinks.end(); ++it ){
		if ( (*it) == o ){
			functorLinks.erase(it);
			break;
		}
	}
}

void Entity::connect (const char *signalName , Entity *destEntity, void(Entity::*fp)()) {		yCONNECT_CODE(0);			}
void Entity::disconnect (const char *signalName , Entity *destEntity, void(Entity::*fp)()) {		yDISCONNECT_CODE(0);			}
void Entity::call ( const char *signalName){							yCALL_CODE();			}

}
#undef yCONNECT_CODE
#undef yCALL_CODE
